package com.ruoyi.SSL.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.SSL.domain.*;
import com.ruoyi.SSL.service.*;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("/SSL/api/v1")
public class SsLApiControllerV1 {

    @Autowired
    private ISslTrusteeshipServiceService trusteeshipServiceService;

    @Autowired
    private ISslTrusteeshipServiceDomainService trusteeshipServiceDomainService;

    @Autowired
    private ISslDomainService domainService;

    @Autowired
    private ISslTrusteeshipServiceDomainService serviceDomainService;

    @Autowired
    private ISslApplyService applyService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private ISslNotificationLogService warmLogService;

    /**
     * 获取到脚本信息
     */
    @ResponseBody
    @GetMapping("/getSerFile")
    public String getSerFile(HttpServletRequest req){
        try {
            //通过token查询是否存在
            String tokenTxt = configService.selectConfigByKey("script.token");
            if(!StrUtil.isNotBlank(tokenTxt)&&StrUtil.equals(req.getHeader("token"), tokenTxt)){
                return "500,token异常！";
            }
            //判断参数
            if(StrUtil.isBlank(req.getParameter("fileType"))){
                return "500,参数异常！";
            }
            HttpRequest request = new HttpRequest(CommUtils.REQ_API_URI+"/SSL/api/v1/getSerFile");
            request.method(Method.POST);
            //先封装参数得到签名值
            JSONObject paramObj = new JSONObject();
            paramObj.set("appId", configService.selectConfigByKey("api.appId"));
            paramObj.set("fileType", req.getParameter("fileType"));
            //得到签名
            String sign = SignUtils.createSign(paramObj, configService.selectConfigByKey("api.appSecret"));
            //赋值必要请求头的值
            request.header("Referer", configService.selectConfigByKey("self.domain"));
            request.header("ssl-sign", sign);   //签名字符串
            request.header("ssl-appid", configService.selectConfigByKey("api.appId"));  //appid
            request.header("ssl-timestamp", String.valueOf(DateUtil.current()));    // 当前时间戳
            //把请求参数赋值到请求中
            request.body(JSONUtil.toJsonStr(paramObj));
            //发起请求
            HttpResponse response = request.execute();
            if(response.getStatus() == 200){
                JSONObject resObj = JSONUtil.parseObj(response.body());
                if(resObj.getInt("code") == 0){
                    JSONObject resultJson = JSONUtil.parseObj(resObj.getStr("data"));
                    return "200,"+resultJson.getStr("fileVersion")+","+CommUtils.REQ_API_URI+resultJson.getStr("filePath").trim();
                }else{
                    return "500,"+resObj.getStr("msg");
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return "500,未知错误！";
    }

    /**
     * 检查token是否有效
     * @param token 需要检查的token
     * @return 返回token是否的AjaxResult对象
     */
    @ResponseBody
    @GetMapping("/checkToken")
    public String checkToken(HttpServletRequest req,String token){
        //检查服务器信息是否存在，不存在则添加服务器信息
        trusteeshipServiceService.getSerInfoByReq(req);
        //通过token查询是否存在
        String tokenTxt = configService.selectConfigByKey("script.token");
        if(StrUtil.isNotBlank(tokenTxt)&&StrUtil.equals(token, tokenTxt)){
            return "200,token可用！";
        }
        return "500,token异常！";
    }

    @ResponseBody
    @GetMapping("/checkSchemeHttps")
    public String checkSchemeHttps(){
        return "200,Https可用！";
    }

    /**
     * 同步服务器的SSL证书到系统
     * @param privateKeyPath 私钥文件路径
     */
    @ResponseBody
    @PostMapping("/synsDomain")
    public String synsDomain(HttpServletRequest req,String privateKeyPath, String sslFilePath,  MultipartFile privateFile, MultipartFile sslFile){
        try {
            //删除无效的部署数据数据，以下这段代码是删除已经删除服务器的托管域名
            trusteeshipServiceDomainService.delStsIdIsNull();
            //先过去到服务器信息
            SslTrusteeshipService trusteeshipService = trusteeshipServiceService.getSerInfoByReq(req);
            //通过token查询是否存在
            String tokenTxt = configService.selectConfigByKey("script.token");
            if(!StrUtil.isNotBlank(tokenTxt)&&StrUtil.equals(req.getHeader("token"), tokenTxt)){
                return "500,token异常！";
            }
            if(sslFilePath.contains("default")){
                return "200,跳过默认的证书文件！";
            }
            String uploadPath = RuoYiConfig.getUploadPath();
            //上传证书文件
            String sslFileUrl = FileUploadUtils.upload(uploadPath+"/sslPemAndKeyFiles", sslFile);
            //上传私钥文件
            String privateFileUrl = FileUploadUtils.upload(uploadPath+"/sslPemAndKeyFiles", privateFile);
            //证书内容
            JSONObject sslInfo = CommUtils.getSSLInfoByFile((uploadPath+"/"+sslFileUrl));
            if(sslInfo == null){
                return "500,证书内容为空！";
            }
            //获取到域名信息
            SslDomain sslDomain = domainService.getByDomain(sslInfo, sslFileUrl, privateFileUrl);
            if(StrUtil.isNotBlank(sslDomain.getStsId())){
                if(!sslDomain.getStsId().contains(String.valueOf(trusteeshipService.getId()))){
                    sslDomain.setStsId(sslDomain.getStsId()+","+trusteeshipService.getId().toString());
                }
            }else{
                sslDomain.setStsId(trusteeshipService.getId().toString());
            }
            if(StrUtil.isBlank(sslDomain.getDeployStatus())){
                sslDomain.setDeployStatus("Y");
            }
            //保存数据
            domainService.updateSslDomain(sslDomain);
            sslDomain.setSerIp(trusteeshipService.getSerIp());
            //执行同步到服务端
            applyService.synsDomain(sslDomain);
            //查询是否存在服务器域名
            SslTrusteeshipServiceDomain serviceDomain = new SslTrusteeshipServiceDomain();
            //赋值属于哪个服务器
            serviceDomain.setStsId(trusteeshipService.getId());
            serviceDomain.setSslDomain(sslInfo.getStr("domainTxt"));
            serviceDomain.setPrivateKeyFilePath(privateKeyPath);
            serviceDomain.setPublicKeyFilePath(sslFilePath);
            //判断是否存在
            List<SslTrusteeshipServiceDomain> serviceDomainList = trusteeshipServiceDomainService.selectSslTrusteeshipServiceDomainList(serviceDomain);
            if(!(serviceDomainList != null && serviceDomainList.size() >0)){
                serviceDomain.setDomainMainId(sslDomain.getId());
                serviceDomain.setSslApplyId(sslDomain.getSslApplyId());
                serviceDomain.setExpiredTime(DateUtil.parse(sslInfo.getStr("endTime")));
                //插入数据
                trusteeshipServiceDomainService.insertSslTrusteeshipServiceDomain(serviceDomain);
                return "200,"+serviceDomain.getSslDomain()+"：SSL文件同步成功！";
            }else{
                return "200,"+serviceDomain.getSslDomain()+"：已同步，跳过该域名！";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "500,同步系统异常！";
        }
    }

    @ResponseBody
    @GetMapping("/getXQSSL")
    public String getXQSSL(HttpServletRequest req){
        SslDomain sslDomain = new SslDomain();
        sslDomain.setStatus("3");
        sslDomain.setIsAutoSsl("Y");
        sslDomain.setDeployStatus("N");
        //限制获取当前请求服务器的需要续签的域名
        SslTrusteeshipService trusteeshipService = trusteeshipServiceService.getSerInfoByReq(req);
        sslDomain.setStsId(trusteeshipService.getId().toString());
        List<SslDomain> domainList = domainService.selectSslDomainList(sslDomain);
        StringBuilder rtnResult = new StringBuilder();
        if(domainList != null && domainList.size() > 0){
            //每次取一个
            sslDomain = domainList.get(0);
            Object tempNum = CacheUtils.get("domain_ssl_num_"+DateUtil.format(new Date(), "YYYYMMdd"));
            int domainSSLNum = 0;
            if(tempNum != null && StringUtils.isNotEmpty(tempNum.toString())){
                domainSSLNum = Integer.parseInt(tempNum.toString());
                if(domainSSLNum == domainList.size()){
                    int cs = Integer.parseInt(CacheUtils.get("domain_ssl_num1_"+DateUtil.format(new Date(), "YYYYMMdd")).toString());
                    if(cs >= 10){
                        sslDomain.setRemark("配置异常，导致重复请求！请检查！脚本陷入死循环！");
                        //保存数据
                        return "500,配置异常，导致重复请求！请检查！脚本陷入死循环！";
                    }else{
                        cs=cs+1;
                        CacheUtils.put("domain_ssl_num1_"+DateUtil.format(new Date(), "YYYYMMdd"), cs);
                    }
                }
            }else{
                CacheUtils.put("domain_ssl_num_"+DateUtil.format(new Date(), "YYYYMMdd"), domainList.size());
                CacheUtils.put("domain_ssl_num1_"+DateUtil.format(new Date(), "YYYYMMdd"), 1);
            }
            //得到证书
            SslApply apply = applyService.selectSslApplyById(sslDomain.getSslApplyId());
            if(apply != null) {
                rtnResult.append(200).append("," + apply.getSslFilePath());
                //查询此域名下有哪些证书需要替换
                SslTrusteeshipServiceDomain serviceDomain = new SslTrusteeshipServiceDomain();
                serviceDomain.setSslDomain(sslDomain.getCertificateDomain());
                List<SslTrusteeshipServiceDomain> serviceDomainList = serviceDomainService.selectSslTrusteeshipServiceDomainList(serviceDomain);
                StringBuilder dirSb = new StringBuilder();
                for (SslTrusteeshipServiceDomain trusteeshipServiceDomain : serviceDomainList) {
                    if(dirSb == null || StringUtils.isBlank(dirSb.toString())){
                        dirSb.append(trusteeshipServiceDomain.getPrivateKeyFilePath()+"&"+trusteeshipServiceDomain.getPublicKeyFilePath());
                    }else{
                        dirSb.append("#"+trusteeshipServiceDomain.getPrivateKeyFilePath()+"&"+trusteeshipServiceDomain.getPublicKeyFilePath());
                    }
                }
                rtnResult.append("," + dirSb.toString()).append("," + sslDomain.getId()).append(","+sslDomain.getCertificateDomain());
                Console.log(rtnResult.toString());
                return rtnResult.toString();
            }
             //  /www/server/panel/vhost/cert/test-erp.schssz.com/privkey.pem&/www/server/panel/vhost/cert/test-erp.schssz.com/fullchain.pem
            //  #/www/server/panel/vhost/cert/test-live.schssz.com/privkey.pem&/www/server/panel/vhost/cert/test-live.schssz.com/fullchain.pem
            //  #/www/server/panel/vhost/cert/www.schssz.com/privkey.pem&/www/server/panel/vhost/cert/www.schssz.com/fullchain.pem
            //  ,384,*.schssz.com
        }else{
            CacheUtils.remove("domain_ssl_num_"+DateUtil.format(new Date(), "YYYYMMdd"));
            CacheUtils.remove("domain_ssl_num1_"+DateUtil.format(new Date(), "YYYYMMdd"));
            return "500,暂无快要到期的证书！";
        }
        return "500,xxxx";
    }

    @ResponseBody
    @GetMapping("/sendErrorMsg/{id}")
    public String sendErrorMsg(@PathVariable("id") Long id){
        try {
            SslDomain sslDomain = domainService.selectSslDomainById(id);
            //发送消息获取到申请记录
            SslApply apply = applyService.selectSslApplyById(sslDomain.getSslApplyId());
            String content ="域名#info#"+sslDomain.getCertificateDomain()+"\n,"
                    +"生效时间#info#"+DateUtil.format(apply.getSslCreateTime(), "yyyy-MM-dd HH:mm")+"\n,"
                    +"到期时间#info#"+DateUtil.format(apply.getExpiredTime(), "yyyy-MM-dd HH:mm")+"\n,";
            //发送通知
            warmLogService.insertLog("2", sslDomain.getCertificateDomain(), "["+sslDomain.getCertificateDomain()+"]证书续签失败",content);
        } catch (Exception e) {
            return "500,未知系统错误！";
        }
        return "200,发送续签失败消息成功！";
    }

    @ResponseBody
    @GetMapping("/udtSllInfo/{id}")
    public String udtSllInfo(@PathVariable("id") Long id){
        try {
            SslDomain sslDomain = domainService.selectSslDomainById(id);
            sslDomain.setDeployStatus("Y");
            domainService.updateSslDomain(sslDomain);
            //发送消息获取到申请记录
            SslApply apply = applyService.selectSslApplyById(sslDomain.getSslApplyId());
            String content ="域名#info#"+sslDomain.getCertificateDomain()+","
                    +"生效时间#info#"+DateUtil.format(apply.getSslCreateTime(), "yyyy-MM-dd HH:mm")+","
                    +"到期时间#info#"+DateUtil.format(apply.getExpiredTime(), "yyyy-MM-dd HH:mm")+",";
            //发送通知
            warmLogService.insertLog("2", sslDomain.getCertificateDomain(), "["+sslDomain.getCertificateDomain()+"]证书续签成功，续签时间："+ DateUtil.format(new Date(), "yyyy-MM-dd HH:mm"),content);
        } catch (Exception e) {
            return "500,未知系统错误！";
        }
        return "200,状态更改成功！";
    }
}
